const path = require("path");
const fs = require("fs").promises;
const hash = require("hash-sum");

const { transform } = require("./_transform");
const { nextId } = require("./_id");
const { trimStart } = require("lodash");
const { getCacheDir } = require("./_tmpdir");

const importerMap = new Map();

async function isExists(filepath) {
  try {
    await fs.stat(filepath);
    return true;
  } catch (err) {
    return false;
  }
}

let tmpDir;

module.exports = (options = {}) => {
  return {
    name: "vue-2-sfc",
    setup(build) {
      build.onResolve({ filter: /.\.vue$/ }, async (args) => {
        let resolveDir = args.resolveDir;
        if (importerMap.has(args.importer)) {
          resolveDir = importerMap.get(args.importer).resolveDir;
        }

        const sourceFileFullPath = path.resolve(resolveDir, args.path);
        const sum = hash(sourceFileFullPath);

        tmpDir = await getCacheDir();

        const id = nextId();
        const tmpFilename = sum;
        const source = await fs.readFile(sourceFileFullPath, "utf-8");
        const result = await transform({
          filename: args.path,
          id,
          source,
          tmpFilename,
        });

        importerMap.set(path.resolve(tmpDir, result.scriptEntry), args);

        await Promise.all(
          result.files.map((it) => {
            const fullPath = path.resolve(tmpDir, it.outfile);
            return fs.writeFile(fullPath, it.code, "utf-8");
          })
        );

        return {
          path: path.resolve(tmpDir, result.entry),
        };
      });

      build.onResolve({ filter: /^tmp:\/\/.+/ }, async (args) => {
        const filename = trimStart(args.path, "tmp://");
        const sourceFileFullPath = path.resolve(tmpDir, filename);

        return {
          path: sourceFileFullPath,
        };
      });

      build.onResolve({ filter: /.*/ }, async (args) => {
        if (args.path.startsWith("tmp://")) {
          return;
        }

        let resolveDir = args.resolveDir;
        if (importerMap.has(args.importer)) {
          resolveDir = importerMap.get(args.importer).resolveDir;
        }

        let filename = args.path;
        let ext = path.extname(args.path);
        if (ext === "") {
          filename = filename + ".js";
        }

        let fullPath = path.resolve(resolveDir, filename);
        const exists = await isExists(fullPath);
        if (!exists) {
          fullPath = path.resolve(resolveDir, args.path + ".ts");
        }

        return {
          path: fullPath,
          namespace: "file",
        };
      });
    },
  };
};
